var handleWindowResize = function() {
    $('#entityContainer').height($(window).height() - $('#entityContainer').position().top - 8);
    $('#entityList').height($('#entityContainer').height() - $('.entityHeader').height() - $('.entityFooter').height() - 4);


    $('#attributeContainer').width($(window).width() - $('#entityContainer').width() - 20);
    $('#landing').width($(window).width() - $('#entityContainer').width() - 20);


    $('#attributeList').height($('#entityList').height() - 48);
};

// Window Resize
$(window).resize(function() {
    handleWindowResize();
});


// Main Object
var explorer = {};

var addCommas = function(nStr) {
    if (typeof nStr === 'undefined') {
        return '';
    }

    var x = nStr.split('.'),
        x1 = x[0],
        x2 = x.length > 1 ? '.' + x[1] : '',
        rgx = /(\d+)(\d{3})/;

    while (rgx.test(x1)) {
        x1 = x1.replace(rgx, '$1' + ',' + '$2');
    }

    return x1 + x2;
};

// -----------------
// Entities
// -----------------

var getEntityIcon = function(objectTypeCode) {
    var img = '',
        dev = '';

    if (parseInt(objectTypeCode, 10) >= 10000) {
        img = '<img align="absmiddle" class="ms-crm-Nav-Subarea-Icon" id="" alt="" src="' + dev + '/_Common/icon.aspx?cache=1&iconType=NavigationIcon&objectTypeCode=' + objectTypeCode + '"/>';
    } else {
        img = '<img class="ms-crm-ImageStrip-ico_18_' + objectTypeCode + '" alt="" src="' + dev + '/_imgs/imagestrips/transparent_spacer.gif"/>';
    }

    return img;
};

var getLargeEntityIcon = function(objectTypeCode) {
    var img = '',
        dev = '';

    if (parseInt(objectTypeCode, 10) >= 10000) {
        img = '<img align="absmiddle" class="ms-crm-Nav-Subarea-Icon" id="" alt="" src="' + dev + '/_Common/icon.aspx?cache=1&iconType=FormHeaderEntityIcon&objectTypeCode=' + objectTypeCode + '"/>';
    } else {
        img = '<img class="ms-crm-ImageStrip-ico_fhe_' + objectTypeCode + '" alt="" src="' + dev + '/_imgs/imagestrips/transparent_spacer.gif"/>';
    }

    return img;
};

var generateEntityTable = function(search) {
    var listing = '',
        i = 0,
        typeCode = '',
        displayName = '',
        logicalName = '',
        entityCount = 0,
        data = explorer.entities;

    for (i = 0; i < data.length; i++) {
        if (explorer.entities[i].IsValidForAdvancedFind === "true") {

            typeCode = data[i].ObjectTypeCode;
            displayName = data[i].DisplayName;
            logicalName = data[i].LogicalName;

            if ((typeCode + ' ' + displayName + ' ' + logicalName).indexOf(search) >= 0) {

                listing += '<tr data-guid="' + data[i].MetadataId + '" data-typecode="' + typeCode + '" data-name="' + logicalName + '" data-display="' + displayName + '">' +
                    '<td class="enitySmallIcon">' + getEntityIcon(typeCode) + '</td>' +
                    '<td class="displayName" title="' + displayName + '">' + displayName + '</td>' +
                    '<td class="logicalName" title="' + logicalName + '">' + logicalName + '</td>' +
                    '</tr>';

                entityCount++;
            }
        }
    }

    $('.entityCount').html(entityCount + " Entities");
    $('.entityTableData').html(listing);

    // Add Event Handlers
    $('.entityTableData tr').bind('click', function() {
        $('.entityTableData tr').removeClass('selectedEntity');

        $(this).addClass('selectedEntity');

        var logicalName = $(this).attr('data-name');

        // Setup Header
        $('#entityHeader .entityName').html($(this).attr('data-display'));
        $('#entityHeader .logicalName').html(logicalName);
        $('#entityHeader .largeIcon').html(getLargeEntityIcon($(this).attr('data-typecode')));

        // Load Attributes
        populateAttributes(logicalName);
    });
};

var loadEntities = function(data) {
    explorer.entities = data;
    generateEntityTable('');
};

var populateEntities = function() {
    JCL.RetrieveAllEntitiesRequest(loadEntities);
};

// Attributes

var sortAttributes = function(a, b) {
    var c1 = a.LogicalName.toLowerCase(),
        c2 = b.LogicalName.toLowerCase();

    if (c1 === c2) {
        return 0;
    } else {
        return (c1 < c2 ? -1 : 1);
    }
};


var loadAttributes = function(data) {
    var listing = '',
        i = 0,
        typeCode = '',
        check = '<span class="check"></span>',
        entityLogicalName = data[0].EntityLogicalName,
        displayName,
        attrCount = 0;

    if (typeof explorer.attributes === 'undefined') {
        explorer.attributes = [];
    }

    explorer.attributes[entityLogicalName] = data;
    data.sort(sortAttributes);

    for (i = 0; i < data.length; i++) {
        displayName = data[i].DisplayName;

        if (displayName.trim() !== "" && data[i].IsValidForRead !== 'false') {
            listing += '<tr data-logicalName="' + data[i].LogicalName + '">' +
                '<td class="displayName" title="' + displayName + '">' + displayName + '</td>' +
                '<td class="logicalName" title="' + data[i].LogicalName + '">' + data[i].LogicalName + '</td>' +
                '<td class="percent">...</td>' +
                '<td class="propertyType">' + data[i].AttributeType + '</td>' +
                '<td class="customizable">' + (data[i].IsCustomAttribute === "true" ? check : "&nbsp;") + '</td>' +
                '<td class="searchable">' + (data[i].IsValidForAdvancedFind === "true" ? check : "&nbsp;") + '</td>' +
                '<td class="spacer">&nbsp;</td>' +
                '</tr>';

            attrCount++;
        }
    }

    $('.attributeCount').html(attrCount + ' attributes');
    $('#attributeList').html('<table class="attributeTableData">' + listing + '</table>');
    $('#entityDetail').show();
    $('#landing').hide();

    getCountOfEntity(entityLogicalName);
};

var populateAttributes = function(logicalName) {
    JCL.RetrieveEntityRequest(logicalName, loadAttributes);
};

var getRecordCountFromDataObject = function (data, entityLogicalName) {
    var totalRecords = data[0].attributes.entity_count.value;

    if (totalRecords === undefined) {
        totalRecords = data[0].attributes.entity_count.value.split(entityLogicalName)[1];
    }

    if (totalRecords === undefined) {
        totalRecords = data[0].attributes.entity_count.value.split(entityLogicalName)[2];
    }

    return totalRecords;
};

var loadEntityCount = function(totalRecords, entityLogicalName) {
    var i = 0,
        attrList = explorer.attributes[entityLogicalName];

    explorer.entities[entityLogicalName] = totalRecords;
    $('.recordCount').html(addCommas(totalRecords) + ' records');

    if (typeof attrList !== 'undefined') {
        for (i = 0; i < attrList.length; i++) {
            if (attrList[i].IsValidForRead !== 'false' && attrList[i].AttributeType !== 'PartyList') {
                getCountOfAttribute(entityLogicalName, attrList[i].LogicalName);
            }
        }
    }     
};

var getPrimaryIdOfEntity = function(entityName) {
    var primaryID = '',
        i = 0;

    for (i = 0; i < explorer.entities.length; i++) {
        if (explorer.entities[i].LogicalName.toLowerCase() === entityName.toLowerCase()) {
            primaryID = explorer.entities[i].PrimaryIdAttribute;
        }
    }

    return primaryID;
};

var getCountOfEntity = function(entityName) {
    var fetch = " " +
        "<fetch mapping='logical' version='1.0' aggregate='true'>" +
        "	<entity name='" + entityName + "'>" +
        "		<attribute name='" + getPrimaryIdOfEntity(entityName) + "' alias='entity_count' aggregate='count' />" +
        "	</entity>" +
        "</fetch>";

    JCL.fetch(
        fetch, 
        function (data) {
            var totalRecords = getRecordCountFromDataObject(data, entityName);
            loadEntityCount(totalRecords, entityName);
        }, 
        function (failed) { 
            if (failed.indexOf('AggregateQueryRecordLimit') > 0) {
                $('#aggregateDialog').dialog({
                    width: 400,
                    modal: true
                });
                loadEntityCount("50001", entityName);
            } else {
                alert('Unknown Error\n' + failed);
            }
        }
    );
};

var loadAttributeCount = function(recordCount, entityLogicalName, fieldName) {
    var total = explorer.entities[entityLogicalName],
        percent,
        graph;

    percent = recordCount / total;
    graph = '<span class="barcontainer"><span class="barfill" style="width:' + (percent * 200).toFixed(0) + 'px;"></span></span>';

    $('#attributeList tr[data-logicalName="' + fieldName + '"] .percent').html('<span class="barvalue">' + (percent * 100.0).toFixed(1) + '%</span>' + graph);

    //console.log("Entity: " + entityLogicalName + "\nField: " + fieldName + "\nCount: " + recordCount);
};

var getCountOfAttribute = function(entityName, fieldName) {
    var fetch = " " +
        "<fetch mapping='logical' version='1.0' aggregate='true'>" +
        "	<entity name='" + entityName + "'>" +
        "		<attribute name='" + getPrimaryIdOfEntity(entityName) + "' alias='entity_count' aggregate='count' />" +
        "		<filter type='and'>" +
        "			<condition attribute='" + fieldName + "' operator='not-null'/>" +
        "		</filter>" +
        "	</entity>" +
        "</fetch>";

    JCL.fetch(
        fetch, 
        function(data) {
            var recordCount = getRecordCountFromDataObject(data, entityName);
            loadAttributeCount(recordCount, entityName, fieldName);
        },
        function (failed) {
            loadAttributeCount("50001", entityName, fieldName);
        }
    );
};

$(function() {
    handleWindowResize();
    populateEntities();

    $('#entityFilter').on('keyup', function() {
        generateEntityTable($(this).val());
    });
});